//采用Data+Clock的方式通信,写和读的数据都是BCD编码
#include "Device/DS1302.h"
#include "Hardware/Timer.h"

#define DS1302Port P1
#define TCLK_Bit (0)
#define TIO_Bit  (1)
#define TRST_Bit (2)

#define TCLK(x) ( (!!(x)) ? SetBit(DS1302Port,TCLK_Bit): ClrBit(DS1302Port,TCLK_Bit) );Delay1us();Delay1us()
#define TIO(x)  ( (!!(x)) ? SetBit(DS1302Port,TIO_Bit ): ClrBit(DS1302Port,TIO_Bit)  );Delay1us();Delay1us()
#define TRST(x) ( (!!(x)) ? SetBit(DS1302Port,TRST_Bit): ClrBit(DS1302Port,TRST_Bit) );Delay1us();Delay1us()

#define Second_Write_Addr  (0x80)
#define Second_Read_Addr   (0x81)
#define Minute_Write_Addr  (0x82)
#define Minute_Read_Addr   (0x83)
#define Hour_Write_Addr    (0x84)
#define Hour_Read_Addr     (0x85)
#define Day_Write_Addr     (0x86)
#define Day_Read_Addr      (0x87)
#define Month_Write_Addr   (0x88)
#define Month_Read_Addr    (0x89)
#define Year_Write_Addr    (0x8C)
#define Year_Read_Addr     (0x8D)
#define Write_Protect_Addr (0x8E)

uint8 BCD2Num(uint8 BCD)
{
	return (BCD>>4)*10+(BCD&0x0f);
}

//可接受最大值99
uint8 Num2BCD(uint8 Num)
{
	if(Num>99)
		return 0;
	return (((Num/10)<<4) | (Num%10) );
}

void DS1302_WriteByte(uint8 addr,byte dat)
{
	uint8 i;
	
	TRST(0); //先拉低RST
	TCLK(0); //拉低时钟
	TRST(1); //拉搞高RST,准备开始写操作
	
	//先写地址
	for(i=0;i<sizeof(addr)*8;++i)
	{
		//上升沿硬件读走数据
		TCLK(0);
		TIO(GetBit(addr,i));
		TCLK(1);
	}

	//再写数据或者指令
	for(i=0;i<sizeof(dat)*8;++i)
	{
		TCLK(0);
		TIO(GetBit(dat,i));
		TCLK(1);
	}
	Delay60us();
	//写完释放
	TRST(0);
	TCLK(0);
}

byte DS1302_ReadByte(uint8 addr)
{
	uint8 i;
	byte dat=0;
	
	TRST(0); //先拉低RST
	TCLK(0); //拉低时钟
	TRST(1); //拉搞高RST,准备开始读操作
	
	//读操作需要先写地址(上升沿),之后读取数据(下降沿)
	for(i=0;i<sizeof(addr)*8;++i)
	{
		//上升沿被读走
		TCLK(0);
		TIO(GetBit(addr,i));
		TCLK(1);
	}

	//读数据
	for(i=0;i<sizeof(dat)*8;++i)
	{
		TCLK(0);
		if(GetBit(DS1302Port,TIO_Bit))
			SetBit(dat,i);
		TCLK(1);
	}
	Delay60us();
	//读完释放
	TRST(0);
	TCLK(0);
	return dat;
}

void DS1302_SetTime(DateTime dt)
{
	DS1302_WriteByte(Write_Protect_Addr,0); //解除写保护
	
	DS1302_WriteByte(Year_Write_Addr,Num2BCD(dt.year));
	DS1302_WriteByte(Month_Write_Addr,Num2BCD(dt.month));
	DS1302_WriteByte(Day_Write_Addr,Num2BCD(dt.day));
	DS1302_WriteByte(Hour_Write_Addr,Num2BCD(dt.hour));
	DS1302_WriteByte(Minute_Write_Addr,Num2BCD(dt.minute));
	DS1302_WriteByte(Second_Write_Addr,Num2BCD(dt.second));
	
	DS1302_WriteByte(Write_Protect_Addr,0x80);//开启写保护
}

DateTime DS1302_GetTime()
{
	DateTime dt;
	dt.year=BCD2Num(DS1302_ReadByte(Year_Read_Addr));
	dt.month=BCD2Num(DS1302_ReadByte(Month_Read_Addr));
	dt.day=BCD2Num(DS1302_ReadByte(Day_Read_Addr));
	dt.hour=BCD2Num(DS1302_ReadByte(Hour_Read_Addr));
	dt.minute=BCD2Num(DS1302_ReadByte(Minute_Read_Addr));
	dt.second=BCD2Num(DS1302_ReadByte(Second_Read_Addr));
	return dt;
}